{ ================================================================= }
{                                                                   }
{  PFFILE -   file saving & retrieving procedures                   }
{                                                                   }
{    VERSION: PC6.1a                                                }
{    CREATED: 22:13:37  10/23/1985                                  }
{    REVISED: 1:56am Jul 01,1989 - revised CLEN to CLEN+1 to allow  }
{    7 digit totals                                                 }
{                                                                   }
{ ================================================================= }

{ ------------------------------------------------------------------------ }
{ Copyright 1982 - 1989 James S Stone, dba Project Control Systems         }
{                                                                          }
{ Licensed under the Apache License, Version 2.0 (the "License");          }
{ you may not use this file except in compliance with the License.         }
{ You may obtain a copy of the License at                                  }
{                                                                          }
{ http://www.apache.org/licenses/LICENSE-2.0                               }
{                                                                          }
{ Unless required by applicable law or agreed to in writing, software      }
{ distributed under the License is distributed on an "AS IS" BASIS,        }
{ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
{ See the License for the specific language governing permissions and      }
{ limitations under the License.                                           }
{ ------------------------------------------------------------------------ }

{$R-}                                   {Range checking off}
{$B+}                                   {Boolean complete evaluation on}
{$S+}                                   {Stack checking on}
{$I+}                                   {I/O checking on}
{$N-}                                   {No numeric coprocessor}
{$V-}                                   {Relaxed var string processing}

unit PfFile;

interface

uses
  Crt,
  Dos,
  Printer,
  PfComm;


procedure PfFileMenu;


implementation



  { pffile  -  retrieve, save, and erase PlanFlow files }
  procedure PfFileMenu;
  type
    Str255 = String[255];               { for DIF & PRN file data }
    ExtType = (Pcs, Dif, Prn);          { extension types }
    ExtArray = array[ExtType] of ExtStr; { see const EXTEN }
    Firec = record                      { file-based item info }
              Ides : String[IDESLEN];
              Icash : CashType;
              EscFlag : Boolean;
            end;
    Fdatatype = record                  { for PCS files }
                  case Boolean of
                    False : (Pdata : Prec); { header for globals }
                    True : (Idata : Firec); { item data }
                end;

  const WILD : NameStr = '*';           { wildcard for listing files }
    FNEW : NameStr = ' [ NEW ]';        { for selecting a new file }
    EXTEN : ExtArray = ('.PCS', '.DIF', '.PRN');
    MAXFILE = 90;                       { maximum of 90 files existing }
		ERRMSG : String[46] = 'Error in saving file  -  diskette may be full.';

	var
		Count,                              { number of files }
    Fnum : Integer;                     { file number }
    Fbuf : NameStr;                     { file name }
    Fdata : Fdatatype;                  { global and item I/O buffer }
    Flist : array[1..MAXFILE] of NameStr; { specified files on disk }
    F : file of Fdatatype;
    T : Text;
    DataFile : String[75];              { data file path & filename }
    DataSpace : Real;                   { percent of data disk used }



    { ListFiles  -  list project files on screen & return how many }
    function ListFiles(Nme : NameStr; Ex : ExtStr) : Integer;
    var
      Count : Integer;                  { number of files read }
      DirInfo : SearchRec;
    begin
      Count := 0;
      FindFirst(DataPath+Nme+Ex, Archive, DirInfo);
      while DosError = 0 do begin
        Inc(Count);
        with DirInfo do
          Flist[Count] := Copy(Name, 1, Pred(Pos('.', Name)));
        FindNext(DirInfo)
      end;
      ListFiles := Count;
    end;                                { ListFiles }



    { displayflist  -  display list of files on screen }
    procedure DisplayFlist;
    var I : Integer;
    begin
      ClrBlok(1, 4, 80, 25);
      GotoXY(1, 4);
      DataColor(Inverse);
      for I := 1 to 6 do
        Write('   FILE   ');
      DataColor(Normal);
      if Count > 0 then
        for I := 1 to Count do begin
          PutAt(I, 15, 10, 1, 4);
          Write(Flist[I]);
        end;
    end;                                { displayflist }



    { getfnum  -  get the name of file to use }
    function GetFnum(var J : Integer) : Integer;
    begin
      State(Point);
      Message(SELECT);
      J := 1;
      GetFnum := ArrowSelect(J, 1, Count, 15, 10, 0, 4);
    end;                                { getfnum }



    { DiskSpace  -  return the percentage of disk space used }
    function DiskSpace(P : PathStr) : Real;
    var Drive : Word;
    begin
      Drive := Ord(P[1])-64;            { datapath's drive }
      DiskSpace := 100.0*(1-DiskFree(Drive)/DiskSize(Drive))
    end;                                { DiskSpace }



    { inputstatus  -  display  of project total and RAM % }
    procedure InputStatus;
    begin
      TextColor(Green);
      TextBackground(Black);
      GotoXY(42, 1);
			Write(RToS(TodateCost, CLEN+1));
      GotoXY(55, 1);
			Write(RToS(TotalCost, CLEN+1));
      GotoXY(64, 1);
      Write(' RAM: ');
      Write((StartMem-MaxAvail+FREEHEAP)*100 div StartMem:3, '%')
    end;                                { inputstatus }



    { fretrieve  -  build a project from a file retrieved from disk }
    procedure Fretrieve;
    var
      IList, Inew : Iptr;
    begin
      HelpNum := 31;
      Count := ListFiles(WILD, EXTEN[Pcs]);
      if Count = 0 then begin
        Error('No project file to retrieve.');
        Exit
      end;

      DisplayFlist;
      LastCh := GetFnum(Fnum);
      if LastCh = Ord(ESC) then
        Exit;

      DataFile := DataPath+Flist[Fnum]+EXTEN[Pcs];
      Assign(F, DataFile);
      {$I-}
      Reset(F);
			if IoResult > 0 then begin
				Error('File not found.');
				Exit
			end;
			FillChar(Fdata, SizeOf(Fdata), 0);
			Read(F, Fdata);
			if IoResult > 0 then begin
				Error('File not found.');
				Exit
			end;
			Pbuf := Fdata.Pdata;
			Pstatus;
			State(Wait);

      IList := Iroot;
      while (Iroot <> nil) do begin     { dispose all existing items }
        Iroot := Iroot^.Next;
        Dispose(IList);
        IList := Iroot;
      end;
      Iroot := nil;
      IList := Iroot;
      TotalCost := 0.0;
      TodateCost := 0.0;
      Hitem := 0;
      Ifirst := 1;
      Inum := 1;
      IfNeeded := True;
      while not Eof(F) do begin
        if NoRoom then begin
          Error('Memory full.  No more items can be added.');
          Close(F);
          Exit
        end;
				Read(F, Fdata);
				if IoResult = 0 then begin
					Ibuf.Ides := Fdata.Idata.Ides;
					Ibuf.Icash := Fdata.Idata.Icash;
					Ibuf.EscFlag := Fdata.Idata.EscFlag;
					Ibuf.ITodate := CalcToDate;
					TodateCost := RRound(TodateCost+Ibuf.ITodate);
					TotalCost := RRound(TotalCost+Ibuf.Icash[TOTPER]);
					Hitem := Hitem+1;
					New(Inew);
					Inew^.Info := Ibuf;
					Inew^.Next := nil;
					if Iroot = nil then
						Iroot := Inew
					else
						IList^.Next := Inew;
					IList := Inew;
					InputStatus;
				end;
      end;
      Close(F);
      {$I+}
    end;                                { fretrieve }



    { fmerge  -  merge a project file to current project }
    procedure Fmerge;
    var IList,
      Inew : Iptr;
      Fstart : 1..MAXYR;                { start year of file }
      OutCount,                         { count of items not merged due to 0 cost }
      I : Integer;
      Ocstr : String[2];                { outcount string }
      NonZero : Boolean;                { merged item has a value }
    begin
      HelpNum := 32;
      Count := ListFiles(WILD, EXTEN[Pcs]);
      if Count = 0 then begin
        Error('No project file to merge.');
				Exit
      end;

      DisplayFlist;
      LastCh := GetFnum(Fnum);
      if LastCh = Ord(ESC) then
				Exit;

      State(Wait);
      Fbuf := Flist[Fnum];
			DataFile := DataPath+Fbuf+EXTEN[Pcs];
      Assign(F, DataFile);
      {$I-}
      Reset(F);
			if IoResult > 0 then begin
				Error('File not found.');
				Exit
			end;

			FillChar(Fdata, SizeOf(Fdata), 0);
			Read(F, Fdata);
			if IoResult > 0 then begin
				Error('File not found.');
				Exit
			end;
			Fstart := Fdata.Pdata.Start;    { merge project start }
      if Abs(Pbuf.Start-Fstart) >= MAXPERYR then begin
        Error('Can''t merge: Starts are more than 9 years apart.');
        Close(F);
				Exit
      end;

      I := 1;
      OutCount := 0;
      IList := Iroot;
      while I < Inum do begin           { get ilist to point to inum }
        IList := IList^.Next;
        I := I+1
      end;
      while not Eof(F) do begin
        if NoRoom then begin
          Error('Memory full.  No more items can be added.');
          Close(F);
					Exit
        end else if Hitem = MAXITEMS then begin
          Error('No more items can be added.');
          Close(F);
					Exit
        end;
				Read(F, Fdata);
				if IoResult = 0 then begin
					FillChar(Ibuf, SizeOf(Ibuf), 0);
					Ibuf.Ides := Fdata.Idata.Ides;
					Ibuf.EscFlag := Fdata.Idata.EscFlag;
					NonZero := False;
					Ibuf.ITodate := 0.0;
					for I := MINPER to MAXPER do begin
						Per := (Fstart-Pbuf.Start)*12+I;
						if Per in [MINPER..MAXPER] then begin
							Ibuf.Icash[Per] := Fdata.Idata.Icash[I];
							if Abs(Ibuf.Icash[Per]) > 0.0 then
								NonZero := True;
							Ibuf.Icash[TOTPER] := RRound(Ibuf.Icash[TOTPER]
																					 +Ibuf.Icash[Per]);
							if (Per >= MINPER) and (Per <= Pbuf.Cutoff) then
								Ibuf.ITodate := RRound(Ibuf.ITodate+Ibuf.Icash[Per]);
						end;                          { if }
					end;                            { for }
					if NonZero then begin
						Hitem := Hitem+1;
						TotalCost := RRound(TotalCost+Ibuf.Icash[TOTPER]);
						TodateCost := RRound(TodateCost+Ibuf.ITodate);
						New(Inew);
						Inew^.Info := Ibuf;
						if Iroot = nil then begin
							Iroot := Inew;
							Inew^.Next := nil;
							Inum := 1
						end else begin
							Inew^.Next := IList^.Next;
							IList^.Next := Inew
						end;
						IList := Inew
					end else                        { if nonzero }
						OutCount := OutCount+1;
					InputStatus;
				end;
      end;                              { while }
      Close(F);
      {$I+}
      if OutCount > 0 then begin
        Str(OutCount, Ocstr);
        Error(Ocstr+' items not merged.');
      end;                              { if }
    end;                                { fmerge }



    { setupsave  -  get name of file to save }
    function SetUpSave(E : ExtType) : Integer;
		label 1, 2;
    const GOODSET : set of Char = ['A'..'Z', 'a'..'z', '0'..'9', '$', '&',
      '#', '@', '!', '%', '''', '`', '(', ')', '-', '{', '}', '_', '/'];
    var I : Integer;
    begin
1:    Count := ListFiles(WILD, EXTEN[E]);
      DisplayFlist;
      if Count < MAXFILE then begin
        Count := Count+1;
        PutAt(Count, 15, 10, 0, 4);
        Write(FNEW);
      end;
      LastCh := GetFnum(Fnum);
      if LastCh = Ord(ESC) then begin
        SetUpSave := LastCh;
				Exit
      end;

      if ((Count = MAXFILE) or (Fnum < Count)) then
        Fbuf := Flist[Fnum]
      else begin
2:      C := #0;
        State(Lbl);
        Fbuf := '';
        LastCh := GetString('Enter file name', Fbuf, 8, C);
        if (C = ESC) then
          goto 1
        else if Fbuf = '' then begin
          SetUpSave := Ord(ESC);
					Exit
        end else
          for I := 1 to Length(Fbuf) do
            if not(Fbuf[I] in GOODSET) then begin
              Error('Illegal character in name.');
              goto 2
            end;                        { if }
      end;                              { else }

      {$I-}
      State(Wait);
			DataFile := DataPath+Fbuf+EXTEN[E];
      if E = Pcs then begin
        Assign(F, DataFile);
        Reset(F)
      end else begin
        Assign(T, DataFile);
        Reset(T);
      end;
      if IoResult = 0 then begin        { file exists }
        if E = Pcs then
          Close(F)
        else
          Close(T);
        State(Menus);
        Menu[0].Brief := 'Cancel';
        Menu[0].Full := 'Do not save  --  try another name';
        Menu[1].Brief := 'Replace';
        Menu[1].Full := 'Erase existing file and replace with new file';
        Choice := MenuChoice(1, Ioff);
        if Choice = 0 then
          goto 1                        { back-up and get another name }
        else if Choice = Ord(ESC) then begin
          SetUpSave := Choice;
					Exit                          { bag it }
        end;
      end;                              { if }
      State(Wait);
      if E = Pcs then
        Rewrite(F)
      else
        Rewrite(T);
      if IoResult > 0 then begin
        Error(ERRMSG);
				SetUpSave := Ord(ESC)
      end;
      {$I+}
    end;                                { setupsave }



    { fsave  -  save a project to a file on disk }
    procedure Fsave;
    var IList : Iptr;
    begin
      HelpNum := 33;
      LastCh := SetUpSave(Pcs);
      if LastCh = Ord(ESC) then
				Exit;

      FillChar(Fdata, SizeOf(Fdata), 0);
      Fdata.Pdata := Pbuf;
      {$I-}
      Write(F, Fdata);
      if IoResult > 0 then begin
				Error(ERRMSG);
				Exit
      end;
      IList := Iroot;
      while IList <> nil do begin
        Fdata.Idata.Ides := IList^.Info.Ides;
        Fdata.Idata.Icash := IList^.Info.Icash;
        Fdata.Idata.EscFlag := IList^.Info.EscFlag;
        Write(F, Fdata);
        if IoResult > 0 then begin
					Error(ERRMSG);
					Exit
        end;
        IList := IList^.Next;
      end;                              { while }
      Close(F);
      {$I+}
    end;                                { fsave }



    { ferase  -  erase a file }
    procedure Ferase;
		label 1, 2;
    var Extension : Integer;
    begin
      HelpNum := 34;
1:    Menu[0].Brief := 'Project';
      Menu[0].Full := 'Erase a project file';
      Menu[1].Brief := 'DIF';
      Menu[1].Full := 'Erase a DIF file';
      Menu[2].Brief := '1-2-3';
      Menu[2].Full := 'Erase a 1-2-3 PRN file';
      Extension := MenuChoice(2, Ion);
      if Extension = 27 then
				Exit;

2:    Count := ListFiles(WILD, EXTEN[ExtType(Extension)]);
      if Count = 0 then begin
        Error('No '+EXTEN[ExtType(Extension)]+' files on disk.');
				Exit
      end;

      DisplayFlist;
      LastCh := GetFnum(Fnum);
      if LastCh = Ord(ESC) then
        goto 1;

      Menu[0].Brief := 'No';
      Menu[0].Full := 'Cancel erasure of selected file';
      Menu[1].Brief := 'Yes';
      Menu[1].Full := 'Erase selected file';
      Choice := MenuChoice(1, Ioff);
      if Choice = 27 then
        goto 2
      else if Choice = 1 then begin
        {$I-}
        State(Wait);
				DataFile := DataPath+Flist[Fnum]+EXTEN[ExtType(Extension)];
        Assign(F, DataFile);
				Erase(F);
				if IoResult > 0 then
					Error('File not found.');
        {$I+}
      end;                              { if }
    end;                                { ferase }



    { fclear  -  clear current project from RAM memory }
    procedure Fclear;
    var IList : Iptr;
    begin
      HelpNum := 35;
      Menu[0].Brief := 'No';
      Menu[0].Full := 'Do not clear the current project from RAM memory';
      Menu[1].Brief := 'Yes';
      Menu[1].Full := 'Clear current project from RAM memory.  Have you Saved it?';
      Choice := MenuChoice(1, Ion);
      if Choice = 1 then begin
        IList := Iroot;
        while (Iroot <> nil) do begin   { dispose all existing items }
          Iroot := Iroot^.Next;
          Dispose(IList);
          IList := Iroot;
        end;
        Iroot := nil;
        TotalCost := 0.0;
        TodateCost := 0.0;
        Hitem := 0;
        Ifirst := 1;
        Inum := 1;
        FillChar(Pbuf, SizeOf(Pbuf), 0);
        Pbuf.Start := 1;
        IfNeeded := True;
      end;                              { if }
    end;                                { fclear }



    { fwrite - write fstr to file, return OK if successful }
    function Fwrite(Fstr : Str255) : Boolean;
    var Ioerr, ClosErr : Integer;
    begin
      {$I-}
      WriteLn(T, Fstr);
      Ioerr := IoResult;
			if Ioerr > 0 then
				Error(ERRMSG);
      {$I+}
      Fwrite := (Ioerr = 0);
    end;                                { fwrite }



    { difhead  -  write DIF header }
    function DifHead(Topic : String80;
                     VecNum, Value : Integer;
                     Title : String80) : Boolean;
    var VecInt, ValInt : String[5];
      Ok : Boolean;
    begin
      Str(VecNum, VecInt);
      Str(Value, ValInt);
      Ok := Fwrite(Topic);
      if Ok then
        Ok := Fwrite(VecInt+','+ValInt);
      if Ok then
        Ok := Fwrite('"'+Title+'"');
      DifHead := not(Ok);               { if I/O error then difhead TRUE }
    end;                                { difhead }



    { difdata  -  write data portion of DIF file }
    function DifData(DataType : Integer; DataValue : Real;
                     DataString : String80) : Boolean;
    var TypeString, ValueString : String[10];
      Ok : Boolean;
    begin
      Str(DataType, TypeString);
      Str(DataValue:1:0, ValueString);
      Ok := Fwrite(TypeString+','+ValueString);
      if Ok then
        Ok := Fwrite(DataString);
      DifData := not(Ok);
    end;                                { difdata }



    { fdif  -  write a DIF file }
    procedure Fdif;
		var
			IList : Iptr;
      I, J : Integer;
    begin
      LastCh := SetUpSave(Dif);
      if LastCh = Ord(ESC) then
				Exit;

			if DifHead('TABLE', 0, 1, Pbuf.Name) then Exit;
			if DifHead('VECTORS', 0, 122, '') then Exit;
			if DifHead('TUPLES', 0, Hitem, '') then Exit;
			if DifHead('LABEL', 1, 1, '') then Exit;
      for I := MINPER to MAXPERYR do begin
        Str(Pbuf.Start+I-1, Stemp);
        for J := 1 to 12 do
					if DifHead('LABEL', (I-1)*12+J+1, 1, Stemp) then Exit;
      end;                              { for i }
			if DifHead('LABEL', 122, 1, '') then Exit;
			if DifHead('LABEL', 1, 2, 'ITEM') then Exit;
      for I := MINPER to MAXPERYR do begin
        for J := 1 to 12 do
          if DifHead('LABEL', (I-1)*12+J+1, 1, Copy(MSTR, J*3-2, 3)) then
						Exit;
      end;                              { for i }
			if DifHead('LABEL', 122, 2, 'TOTAL') then Exit;
			if DifHead('DATA', 0, 0, '') then Exit;

      IList := Iroot;
      while IList <> nil do begin
        Ibuf := IList^.Info;
				if DifData(-1, 0, 'BOT') then Exit;
				if DifData(1, 0, '"'+Ibuf.Ides+'"') then Exit;
        for I := MINPER to MAXPER do
					if DifData(0, Ibuf.Icash[I], 'V') then Exit;
				if DifData(0, Ibuf.Icash[TOTPER], 'V') then Exit;
        IList := IList^.Next;
      end;                              { while }
			if DifData(-1, 0, 'EOD') then Exit;
      Close(T);
    end;                                { fdif }



    { fprn  -  write a PRN file }
    procedure Fprn;
    var IList : Iptr;
      I, J, K,
      LastYr : Integer;                 { zero-based last year with costs }
      Fstr : Str255;                    { data string }
      SubFStr : Str20;                  { data sub-string }

    begin
      LastCh := SetUpSave(Prn);
      if LastCh = Ord(ESC) then
				Exit;

      IList := Iroot;                   { get last year with costs }
      LastYr := 1;
      while IList <> nil do begin
        Ibuf := IList^.Info;
        for Per := MINPER to MAXPER do
          if (Abs(Ibuf.Icash[Per]) > 0.1) and (Per > LastYr) then
            LastYr := Per;
        IList := IList^.Next;
      end;                              { while }
      LastYr := (LastYr-1) div 12+1;

      if Pbuf.Name = '' then
        SubFStr := '[ Unnamed ]'
      else
        SubFStr := Pbuf.Name;
			if not Fwrite('"PROJECT:","'+SubFStr+'"') then Exit;

      if Pbuf.Cutoff = 0 then begin
				if not Fwrite('"CUTOFF:","NONE"') then Exit
      end else begin
        Str(Pbuf.Cutoff div 12+Pbuf.Start, Fstr);
        if not Fwrite('"CUTOFF:","'+Copy(MSTR, (Pbuf.Cutoff-1) mod 12*3+1, 3)+
											' '+Fstr+'"') then Exit;
      end;

			if not Fwrite(#13#10'"ESCALATION RATES"') then Exit;
			if not Fwrite('"YEAR","RATE %"') then Exit;
      Str(Pbuf.Prior:1:1, SubFStr);
			if not Fwrite('"PRIOR",'+SubFStr) then Exit;
      for I := 0 to LastYr do begin
        Str(I+Pbuf.Start:0, Fstr);
        Str(Pbuf.ESC[I+1]:1:1, SubFStr);
        Fstr := Fstr+','+SubFStr;
				if not Fwrite(Fstr) then Exit
      end;                              { for }

      for I := 1 to LastYr do begin     { for each year... }
        Fstr := #13#10'"",""';
        Str(I+Pbuf.Start-1:0, SubFStr);
        for J := 1 to 12 do
          Fstr := Fstr+','+SubFStr;
				if not Fwrite(Fstr) then Exit; { write year }
        Fstr := '"ITEM","DESCRIPTION"';
        for J := 1 to 12 do
          Fstr := Fstr+',"'+Copy(MSTR, J*3-2, 3)+'"';
				if not Fwrite(Fstr) then Exit; { write months }

        K := 1;
        IList := Iroot;
        while IList <> nil do begin
          Ibuf := IList^.Info;
          Str(K, Fstr);
          Fstr := Fstr+',"'+Ibuf.Ides+'"';
          { (i-1)*12 + 1 to (i-1)*12 + 12 }
          for J := 12*I-11 to 12*I do begin
            if Round(Ibuf.Icash[J]) = 0 then
              SubFStr := '""'
            else
              Str(Ibuf.Icash[J]:0:0, SubFStr);
            Fstr := Fstr+','+SubFStr;
          end;
					if not Fwrite(Fstr) then Exit; { write costs }
          K := K+1;
          IList := IList^.Next;
        end;                            { while }
      end;                              { for i }
      Close(T);
    end;                                { fprn }



    { fxport  -  export current project to DIF or PRN file }
    procedure Fxport;
    begin
      HelpNum := 36;
      Menu[0].Brief := 'DIF';
      Menu[0].Full := 'Export the current project to a DIF file';
      Menu[1].Brief := '1-2-3';
      Menu[1].Full := 'Export the current project to a 1-2-3 PRN file';
      Choice := MenuChoice(1, Ion);
      case Choice of
        0 : Fdif;
        1 : Fprn;
      end;
    end;                                { fxport }



    { Fpath  -  change the path for project and DIF data files }
    procedure Fpath;
    var
      OldPath : DirStr;
      L : Integer;
    begin
      HelpNum := 50;
      State(Lbl);
      C := #0;
      OldPath := DataPath;
      L := Length(DataPath);
      if (L > 3) and (DataPath[L] = '\') then
        Delete(DataPath, L, 1);
      LastCh := GetString('Enter new path', DataPath, 67, C);
      if C = ESC then begin
        DataPath := OldPath;
        Exit
      end else begin
        DataPath := FExpand(DataPath);
        {$I-}
        ChDir(DataPath);
        if IoResult > 0 then begin
          Error('Path not found.');
          DataPath := OldPath;
        end;
        ChDir(ProgPath);
        {$I+}
        if DataPath[Length(DataPath)] <> '\' then
          DataPath := DataPath+'\'
      end;
    end;                                { Fpath }



  begin
    repeat
      HelpNum := 30;
      DataSpace := DiskSpace(DataPath);
      DisplayIlist(GROUPOFF);
      Pstatus;
      GotoXY(64, 1);
      Write('Disk: ', DataSpace:3:0, '%');
      State(Menus);
      Menu[0].Brief := 'Retrieve';
      Menu[0].Full := 'Erase the current project and read a project file';
      Menu[1].Brief := 'Merge';
      Menu[1].Full := 'Merge a project file with the current project';
      Menu[2].Brief := 'Save';
      Menu[2].Full := 'Store the current project in a project file';
      Menu[3].Brief := 'Erase';
      Menu[3].Full := 'Erase a project, DIF, or 1-2-3 PRN file';
      Menu[4].Brief := 'Clear';
      Menu[4].Full := 'Clear the current project from RAM memory';
      Menu[5].Brief := 'Xport';
      Menu[5].Full := 'Export the current project to a DIF or 1-2-3 PRN file';
      Menu[6].Brief := 'Path';
      Menu[6].Full := 'Set the DOS path for data and report files';
      Menu[7].Brief := 'Quit';
      Menu[7].Full := 'Leave the File menu and return to the Main Menu';
      Choice := MenuChoice(7, Ion);
      case Choice of
        0 : Fretrieve;
        1 : Fmerge;
        2 : Fsave;
        3 : Ferase;
        4 : Fclear;
        5 : Fxport;
        6 : Fpath;
        27,
				7 : Exit;
      end;                              { case }
    until False = True;
  end;                                  { pffile }
end.
